#pragma once
#ifndef Systems_H
#define Systems_H

#include "SystemBase.h"
#include <vector>

using namespace std;

namespace ManchyGL
{
	class Systems:public SystemBase
	{
	private:
		vector<SystemBase*> *_systems;
		vector<SystemBase*> *_awakeSystems;
		vector<SystemBase*> *_startSystems;
		vector<SystemBase*> *_preUpdateSystems;
		vector<SystemBase*> *_updateSystems;
		vector<SystemBase*> *_lateupdateSystems;
		vector<SystemBase*> *_renderSystems;
		vector<SystemBase*> *_predestroySystems;
		vector<SystemBase*> *_destroySystems;


	public:
		Systems()
		{
			_systems = new vector<SystemBase*>();
			_awakeSystems = new vector<SystemBase*>();
			_startSystems = new vector<SystemBase*>();
			_preUpdateSystems = new vector<SystemBase*>();
			_updateSystems = new vector<SystemBase*>();
			_lateupdateSystems = new vector<SystemBase*>();
			_renderSystems = new vector<SystemBase*>();
			_predestroySystems = new vector<SystemBase*>();
			_destroySystems = new vector<SystemBase*>();
		}

		~Systems()
		{
			vector<SystemBase*>::iterator iter;
			if (NULL != _systems)
			{
				for (iter = _systems->begin(); iter != _systems->end(); ++iter)
					delete (*iter);
				delete _systems;
				_systems = NULL;
			}

			if (NULL != _awakeSystems)
			{
				delete _awakeSystems;
				_awakeSystems = NULL;
			}

			if (NULL != _startSystems)
			{
				delete _startSystems;
				_startSystems = NULL;
			}
			if (NULL != _preUpdateSystems)
			{
				delete _preUpdateSystems;
				_preUpdateSystems = NULL;
			}

			if (NULL != _updateSystems)
			{
				delete _updateSystems;
				_updateSystems = NULL;
			}
			if (NULL != _lateupdateSystems)
			{
				delete _lateupdateSystems;
				_lateupdateSystems = NULL;
			}
			if (NULL != _renderSystems)
			{
				delete _renderSystems;
				_renderSystems = NULL;
			}

			if (NULL != _predestroySystems)
			{
				delete _predestroySystems;
				_predestroySystems = NULL;
			}

			if (NULL != _destroySystems)
			{
				delete _destroySystems;
				_destroySystems = NULL;
			}
		}

		virtual SystemFlags GetFlags()
		{
			return SystemFlags::All;
		}

		void AddSystem(SystemBase* system)
		{
			_systems->push_back(system);

			SystemFlags flags = system->GetFlags();
			if ((flags & SystemFlags::OnAwake) != 0)
				_awakeSystems->push_back(system);

			if ((flags & SystemFlags::OnStart) != 0)
				_startSystems->push_back(system);

			if((flags & SystemFlags::OnPreUpdate) != 0)
				_preUpdateSystems->push_back(system);

			if ((flags & SystemFlags::OnPreUpdate) != 0)
				_preUpdateSystems->push_back(system);

			if ((flags & SystemFlags::OnUpdate) != 0)
				_updateSystems->push_back(system);

			if ((flags & SystemFlags::OnLateUpdate) != 0)
				_lateupdateSystems->push_back(system);

			if ((flags & SystemFlags::OnRender) != 0)
				_renderSystems->push_back(system);

			if ((flags & SystemFlags::OnPreDestroy) != 0)
				_predestroySystems->push_back(system);

			if ((flags & SystemFlags::OnDestroy) != 0)
				_destroySystems->push_back(system);
		}

		virtual void OnAwake(Application* context)
		{
			for (int i = 0; i < _awakeSystems->size(); ++i)
				(*_awakeSystems)[i]->OnAwake(context);
		}

		virtual void OnStart()
		{
			for (int i = 0; i < _startSystems->size(); ++i)
				(*_startSystems)[i]->OnStart();
		}

		virtual void OnPreUpdate(float time, float deltaTime)
		{
			for (int i = 0; i < _preUpdateSystems->size(); ++i)
				(*_preUpdateSystems)[i]->OnPreUpdate(time, deltaTime);
		}

		virtual void OnUpdate(float time, float deltaTime)
		{
			for (int i = 0; i < _updateSystems->size(); ++i)
				(*_updateSystems)[i]->OnUpdate(time, deltaTime);
		}

		virtual void OnLateUpdate(float time, float deltaTime)
		{
			for (int i = 0; i < _lateupdateSystems->size(); ++i)
				(*_lateupdateSystems)[i]->OnLateUpdate(time, deltaTime);
		}

		virtual void OnRender()
		{
			for (int i = 0; i < _renderSystems->size(); ++i)
				(*_renderSystems)[i]->OnRender();
		}

		virtual void OnPreDestroy()
		{
			for (int i = 0; i < _predestroySystems->size(); ++i)
				(*_predestroySystems)[i]->OnPreDestroy();
		}

		virtual void OnDestroy()
		{
			for (int i = 0; i < _destroySystems->size(); ++i)
				(*_destroySystems)[i]->OnDestroy();
		}
	};
}
#endif